import 'dart:async';
import 'package:business_plugin/business/config_business/config_business.dart';
import 'package:business_plugin/business/report_utils/report_utils.dart';
import 'package:business_plugin/utils/business_tools.dart';
import 'package:get/get.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:flutter/foundation.dart';

class AdMobService extends GetxService {
  static AdMobService get to => Get.find();

  // 开屏广告ID
  final String _flyOpenId = ConfigBusiness.config.releaseAdvertisement
      ? ConfigBusiness.config.flyOpenId // 发布版广告ID
      : 'ca-app-pub-3940256099942544/5575463023'; // 测试广告ID
  // 插屏广告ID
  final String _bannerAdId = ConfigBusiness.config.releaseAdvertisement
      ? ConfigBusiness.config.bannerAdId // 发布版广告ID
      : 'ca-app-pub-3940256099942544/4411468910'; // 测试广告ID
  // 激励广告ID
  final String _rewardedAdId = ConfigBusiness.config.releaseAdvertisement
      ? ConfigBusiness.config.rewardedAdId // 发布版广告ID
      : 'ca-app-pub-3940256099942544/1712485313'; // 测试广告ID

  // // 开屏广告ID
  // final String _flyOpenId = ConfigBusiness.flyOpenId;
  // // 插屏广告ID
  // final String _bannerAdId = ConfigBusiness.bannerAdId;

  // 开屏广告对象
  AppOpenAd? _appOpenAd;
  // 开屏广告加载状态
  bool _isAppOpenAdLoaded = false;
  bool _isAppOpenAdShowing = false;
  //请求开屏广告的时间
  int _appOpenAdRequestTime = 0;
  DateTime? _appOpenAdLoadTime;

  // 插屏广告对象
  InterstitialAd? _interstitialAd;
  // 插屏广告加载状态
  bool _isInterstitialAdLoaded = false;
  bool _isInterstitialAdShowing = false;
  // 请求插屏广告的时间
  int _interstitialAdRequestTime = 0;

  // 激励广告对象
  RewardedAd? _rewardedAd;
  // 激励广告加载状态
  bool _isRewardedAdLoaded = false;
  bool _isRewardedAdShowing = false;
  // 请求激励广告的时间
  int _rewardedAdRequestTime = 0;

  // 重试机制
  int _appOpenAdRetryAttempt = 0;
  Timer? _appOpenRetryTimer;
  int _interstitialAdRetryAttempt = 0;
  Timer? _interstitialRetryTimer;
  int _rewardedAdRetryAttempt = 0;
  Timer? _rewardedRetryTimer;
  final int _maxRetryCount = 3;

  // 开屏广告回调
  Function()? _onAppOpenAdClosedCallback;
  Function()? _onAppOpenAdFailedCallback;
  // 插屏广告回调
  Function()? _onInterstitialAdClosedCallback;
  Function()? _onInterstitialAdFailedCallback;
  // 激励广告回调
  Function()? _onRewardedAdClosedCallback;
  Function()? _onRewardedAdFailedCallback;

  @override
  void onInit() async {
    super.onInit();
    await initAdMob();
  }

  Future<void> initAdMob() async {
    // 初始化 MobileAds SDK
    await MobileAds.instance.initialize();

    // 设置应用透明度测量
    await MobileAds.instance.updateRequestConfiguration(
      RequestConfiguration(
        tagForChildDirectedTreatment: TagForChildDirectedTreatment.unspecified,
        tagForUnderAgeOfConsent: TagForUnderAgeOfConsent.unspecified,
        testDeviceIds: [
          'EMULATOR', // 所有模拟器
          kDebugMode ? ConfigBusiness.config.googleTestDeviceId : '', // Google 提供的测试设备标识符
        ],
      ),
    );
    loadAppOpenAd(); // 加载开屏广告
    loadInterstitialAd(); // 加载插屏广告
    loadRewardedAd(); // 加载激励广告
  }

  // 加载开屏广告
  void loadAppOpenAd() {
    if (_flyOpenId.isEmpty) {
      BusinessTools.log('开屏广告ID为空，无法加载开屏广告');
      return;
    }
    if (_isAppOpenAdLoaded) return;
    //上报
    // ConfigBusiness.adRequest?.call(BusinessAdmobType.appOpenAd);
    DateTime date = DateTime.now();
    ReportUtils.logEvent("ad_request", properties: {
      "ad_type": "sp_show 开屏广告",
    });
    BusinessTools.log('Loading app open ad...');
    AppOpenAd.load(
      adUnitId: _flyOpenId,
      request: const AdRequest(),
      adLoadCallback: AppOpenAdLoadCallback(
        onAdLoaded: (AppOpenAd ad) {
          //App open ad loaded successfully
          //当前时间-date，获得多少秒，向上取整
          final duration = DateTime.now().difference(date);
          _appOpenAdRequestTime = (duration.inMilliseconds / 1000.0).ceil();

          //上报
          ReportUtils.logEvent("ad_fill", properties: {
            "ad_type": "sp_show 开屏广告",
            "pass_time": _appOpenAdRequestTime,
          });

          _appOpenAd = ad;
          _isAppOpenAdLoaded = true;
          _appOpenAdLoadTime = DateTime.now();
          _appOpenAdRetryAttempt = 0;
          // 设置开屏广告回调
          _setAppOpenAdCallbacks();
        },
        onAdFailedToLoad: (LoadAdError error) {
          BusinessTools.log('App open ad failed to load: ${error.message}');
          _isAppOpenAdLoaded = false;
          _appOpenAd = null;

          final duration = DateTime.now().difference(date);
          _appOpenAdRequestTime = (duration.inMilliseconds / 1000.0).ceil();
          // 重试加载
          _retryAppOpenAd();
        },
      ),
    );
  }

  // 设置开屏广告回调
  void _setAppOpenAdCallbacks() {
    if (_appOpenAd == null) return;

    // 设置收益监听器
    _appOpenAd!.onPaidEvent = (ad, valueMicros, precision, currencyCode) {
      profitReport(
          ad: ad, valueMicros: valueMicros, precision: precision, currencyCode: currencyCode, adFormat: "Splash");
    };

    _appOpenAd!.fullScreenContentCallback = FullScreenContentCallback(
      onAdShowedFullScreenContent: (ad) {
        BusinessTools.log('应用打开广告显示了全屏内容');
        _isAppOpenAdShowing = true;
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        BusinessTools.log('应用打开广告展示失败: ${error.message}');
        _isAppOpenAdShowing = false;
        ad.dispose();
        _isAppOpenAdLoaded = false;
        _appOpenAd = null;
        _onAppOpenAdFailedCallback?.call();

        // 重新加载新广告
        loadAppOpenAd();
      },
      onAdDismissedFullScreenContent: (ad) {
        BusinessTools.log('应用打开后广告被关闭了');
        _isAppOpenAdShowing = false;
        ad.dispose();
        _isAppOpenAdLoaded = false;
        _appOpenAd = null;
        _onAppOpenAdClosedCallback?.call();

        // 重新加载新广告
        loadAppOpenAd();
      },
    );
  }

  // 重试加载开屏广告
  void _retryAppOpenAd() {
    // if (_appOpenAdRetryAttempt >= _maxRetryCount) return;

    _appOpenAdRetryAttempt++;
    // 将线性延迟改为指数延迟
    int retryDelay = (1 << _appOpenAdRetryAttempt).clamp(1, 256);
    BusinessTools.log('App open ad retry in ${retryDelay}s (attempt: $_appOpenAdRetryAttempt)');

    _cancelAppOpenRetryTimer();
    _appOpenRetryTimer = Timer(Duration(seconds: retryDelay), loadAppOpenAd);
  }

  // 取消重试定时器
  void _cancelAppOpenRetryTimer() {
    _appOpenRetryTimer?.cancel();
    _appOpenRetryTimer = null;
  }

  // 检查广告是否过期（4小时有效期）
  bool _isAppOpenAdExpired() {
    if (_appOpenAdLoadTime == null) return true;
    return DateTime.now().difference(_appOpenAdLoadTime!).inHours >= 4;
  }

  // 显示开屏广告
  Future<bool> showAppOpenAd({
    required String position,
    Function()? onAdClosedCallback,
    Function()? onAdFailedCallback,
  }) async {
    //上报
    ReportUtils.logEvent("ad_trigger", properties: {
      "position": position,
      "ad_type": "sp_show 开屏广告",
    });

    _onAppOpenAdClosedCallback = onAdClosedCallback;
    _onAppOpenAdFailedCallback = onAdFailedCallback;
    bool res = true;
    String errorMessage = '';
    // 检查开屏广告是否正在显示
    if (_isAppOpenAdShowing) {
      BusinessTools.log('开屏广告已经在展示中');
      res = false;
      errorMessage = '开屏广告已经在展示中';
    }

    //检查插屏广告是否正在显示
    if (_isInterstitialAdShowing) {
      BusinessTools.log('插屏广告正在展示中，无法显示开屏广告');
      res = false;
      errorMessage = '插屏广告正在展示中，无法显示开屏广告';
    }

    // 检查广告是否已加载且未过期
    if (!_isAppOpenAdLoaded || _appOpenAd == null) {
      BusinessTools.log('开屏广告未准备好');
      loadAppOpenAd();
      _onAppOpenAdFailedCallback?.call();
      res = false;
      errorMessage = '开屏广告未准备好';
    }

    // 检查广告是否过期
    if (_isAppOpenAdExpired()) {
      BusinessTools.log('开屏广告已过期');
      _appOpenAd?.dispose();
      _appOpenAd = null;
      _isAppOpenAdLoaded = false;
      loadAppOpenAd();
      _onAppOpenAdFailedCallback?.call();
      res = false;
      errorMessage = '开屏广告已过期';
    }
    if (!res) {
      ReportUtils.logEvent("ad_show_fail", properties: {
        "position": position,
        "ad_type": "sp_show 开屏广告",
        "error": errorMessage,
        "pass_time": _appOpenAdRequestTime,
      });
      return res;
    }

    // 显示广告
    BusinessTools.log('Showing app open ad');
    ReportUtils.logEvent("sp_show", properties: {
      "position": position,
    });
    await _appOpenAd!.show();
    ConfigBusiness.isLoadingShowAppOpenAd = true; // 设置标志位，表示加载过开屏广告
    return true;
  }

  // 检查开屏广告是否可显示
  bool isAppOpenAdReady() {
    return _isAppOpenAdLoaded && _appOpenAd != null && !_isAppOpenAdShowing && !_isAppOpenAdExpired();
  }

  // 插屏广告相关方法 =====================

  // 加载插屏广告
  void loadInterstitialAd() {
    if (_bannerAdId.isEmpty) {
      BusinessTools.log('插屏广告ID为空，无法加载插屏广告');
      return;
    }
    if (_isInterstitialAdLoaded) return;
    //上报
    // ConfigBusiness.adRequest?.call(BusinessAdmobType.interstitialAd);
    DateTime date = DateTime.now();

    ReportUtils.logEvent("ad_request", properties: {
      "ad_type": "iv_show 插屏广告",
    });
    BusinessTools.log('Loading interstitial ad...');

    InterstitialAd.load(
      adUnitId: _bannerAdId,
      request: const AdRequest(),
      adLoadCallback: InterstitialAdLoadCallback(
        onAdLoaded: (InterstitialAd ad) {
          BusinessTools.log('插屏广告加载成功');
          final duration = DateTime.now().difference(date);
          _interstitialAdRequestTime = (duration.inMilliseconds / 1000.0).ceil();

          //上报
          ReportUtils.logEvent("ad_fill", properties: {
            "ad_type": "iv_show 插屏广告",
            "pass_time": _interstitialAdRequestTime,
          });

          _interstitialAd = ad;
          _isInterstitialAdLoaded = true;
          _interstitialAdRetryAttempt = 0;

          // 设置插屏广告回调
          _setInterstitialAdCallbacks();
        },
        onAdFailedToLoad: (LoadAdError error) {
          BusinessTools.log('插屏广告加载失败: ${error.message}');
          _isInterstitialAdLoaded = false;
          _interstitialAd = null;
          final duration = DateTime.now().difference(date);
          _interstitialAdRequestTime = (duration.inMilliseconds / 1000.0).ceil();
          // 重试加载
          _retryInterstitialAd();
        },
      ),
    );
  }

  // 设置插屏广告回调
  void _setInterstitialAdCallbacks() {
    if (_interstitialAd == null) return;

    // 设置收益监听器
    _interstitialAd!.onPaidEvent = (ad, valueMicros, precision, currencyCode) {
      profitReport(
          ad: ad, valueMicros: valueMicros, precision: precision, currencyCode: currencyCode, adFormat: "Interstitial");
    };

    _interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
      onAdShowedFullScreenContent: (ad) {
        BusinessTools.log('插屏广告展示全屏内容');
        _isInterstitialAdShowing = true;
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        BusinessTools.log('插屏广告展示失败: ${error.message}');
        _isInterstitialAdShowing = false;
        ad.dispose();
        _isInterstitialAdLoaded = false;
        _interstitialAd = null;
        _onInterstitialAdFailedCallback?.call();

        // 重新加载新广告
        loadInterstitialAd();
      },
      onAdDismissedFullScreenContent: (ad) {
        BusinessTools.log('插屏广告被关闭');
        _isInterstitialAdShowing = false;
        ad.dispose();
        _isInterstitialAdLoaded = false;
        _interstitialAd = null;
        _onInterstitialAdClosedCallback?.call();

        // 重新加载新广告
        loadInterstitialAd();
      },
    );
  }

  // 重试加载插屏广告
  void _retryInterstitialAd() {
    // if (_interstitialAdRetryAttempt >= _maxRetryCount) return;

    _interstitialAdRetryAttempt++;
    int retryDelay = (1 << _interstitialAdRetryAttempt).clamp(1, 256);
    BusinessTools.log('插屏广告将在 $retryDelay秒后重试 (尝试: $_interstitialAdRetryAttempt)');

    _cancelInterstitialRetryTimer();
    _interstitialRetryTimer = Timer(Duration(seconds: retryDelay), loadInterstitialAd);
  }

  // 取消插屏广告重试定时器
  void _cancelInterstitialRetryTimer() {
    _interstitialRetryTimer?.cancel();
    _interstitialRetryTimer = null;
  }

  // 显示插屏广告
  Future<bool> showInterstitialAd({
    required String title,
    Function()? onAdClosedCallback,
    Function()? onAdFailedCallback,
  }) async {
    //上报
    ReportUtils.logEvent("ad_trigger", properties: {
      "position": title,
      "ad_type": "iv_show 插屏广告",
    });
    //插屏多上报一次
    ReportUtils.logEvent("iv_position", properties: {
      "position": title,
    });

    _onInterstitialAdClosedCallback = onAdClosedCallback;
    _onInterstitialAdFailedCallback = onAdFailedCallback;

    bool res = true;
    String errorMessage = '';
    // 检查广告是否正在显示
    if (_isInterstitialAdShowing) {
      BusinessTools.log('插屏广告已经在展示中');
      res = false;
      errorMessage = '插屏广告已经在展示中';
    }

    // 检查广告是否已加载
    if (!_isInterstitialAdLoaded || _interstitialAd == null) {
      BusinessTools.log('插屏广告未准备好');
      loadInterstitialAd();
      _onInterstitialAdFailedCallback?.call();
      res = false;
      errorMessage = '插屏广告未准备好';
    }
    if (!res) {
      ReportUtils.logEvent("ad_show_fail", properties: {
        "position": title,
        "ad_type": "iv_show 插屏广告",
        "error": errorMessage,
        "pass_time": _interstitialAdRequestTime,
      });
      //插屏展示失败，在多报一次
      ReportUtils.logEvent("iv_pull_judge", properties: {
        "position": title,
        "fail_reason": errorMessage,
      });
      return res;
    }
    // 显示广告
    BusinessTools.log('正在显示插屏广告');
    //上报
    ReportUtils.logEvent("iv_show", properties: {
      "position": title,
    });
    await _interstitialAd!.show();
    return true;
  }

  // 激励广告相关方法 =====================
  // 加载激励广告
  void loadRewardedAd() {
    if (_rewardedAdId.isEmpty) {
      BusinessTools.log('激励广告ID为空，无法加载激励广告');
      return;
    }
    if (_isRewardedAdLoaded) return;
    //上报
    DateTime date = DateTime.now();
    ReportUtils.logEvent("ad_request", properties: {
      "ad_type": "rv_show 激励广告",
    });
    BusinessTools.log('Loading rewarded ad...');

    RewardedAd.load(
      adUnitId: _rewardedAdId,
      request: const AdRequest(),
      rewardedAdLoadCallback: RewardedAdLoadCallback(
        onAdLoaded: (RewardedAd ad) {
          BusinessTools.log('激励广告加载成功');
          final duration = DateTime.now().difference(date);
          _rewardedAdRequestTime = (duration.inMilliseconds / 1000.0).ceil();
          //上报
          ReportUtils.logEvent("ad_fill", properties: {
            "ad_type": "rv_show 激励广告",
            "pass_time": _rewardedAdRequestTime,
          });

          _rewardedAd = ad;
          _isRewardedAdLoaded = true;
          _rewardedAdRetryAttempt = 0;

          // 设置激励广告回调
          _setRewardedAdCallbacks();
        },
        onAdFailedToLoad: (LoadAdError error) {
          BusinessTools.log('激励广告加载失败: ${error.message}');
          _isRewardedAdLoaded = false;
          _rewardedAd = null;
          final duration = DateTime.now().difference(date);
          _rewardedAdRequestTime = (duration.inMilliseconds / 1000.0).ceil();
          // 重试加载
          _retryRewardedAd();
        },
      ),
    );
  }

  // 设置激励广告回调
  void _setRewardedAdCallbacks() {
    if (_rewardedAd == null) return;

    // 设置收益监听器
    _rewardedAd!.onPaidEvent = (ad, valueMicros, precision, currencyCode) {
      profitReport(
          ad: ad, valueMicros: valueMicros, precision: precision, currencyCode: currencyCode, adFormat: "Rewarded");
    };

    _rewardedAd!.fullScreenContentCallback = FullScreenContentCallback(
      onAdShowedFullScreenContent: (ad) {
        BusinessTools.log('激励广告展示全屏内容');
        _isRewardedAdShowing = true;
      },
      onAdFailedToShowFullScreenContent: (ad, error) {
        BusinessTools.log('激励广告展示失败: ${error.message}');
        _isRewardedAdShowing = false;
        ad.dispose();
        _isRewardedAdLoaded = false;
        _rewardedAd = null;
        _onRewardedAdFailedCallback?.call();

        // 重新加载新广告
        loadRewardedAd();
      },
      onAdDismissedFullScreenContent: (ad) {
        BusinessTools.log('激励广告被关闭');
        _isRewardedAdShowing = false;
        ad.dispose();
        _isRewardedAdLoaded = false;
        _rewardedAd = null;
        _onRewardedAdClosedCallback?.call();

        // 重新加载新广告
        loadRewardedAd();
      },
    );
  }

  // 重试加载激励广告
  void _retryRewardedAd() {
    // if (_rewardedAdRetryAttempt >= _maxRetryCount) return;
    _rewardedAdRetryAttempt++;
    int retryDelay = (1 << _rewardedAdRetryAttempt).clamp(1, 256);
    BusinessTools.log('激励广告将在 $retryDelay秒后重试 (尝试: $_rewardedAdRetryAttempt)');
    _cancelInterstitialRetryTimer();
    _rewardedRetryTimer = Timer(Duration(seconds: retryDelay), loadRewardedAd);
  }

  // 取消激励广告重试定时器
  void _cancelRewardedRetryTimer() {
    _rewardedRetryTimer?.cancel();
    _rewardedRetryTimer = null;
  }

  // 显示激励广告
  Future<bool> showRewardedAd({
    required String title,
    //系统会在用户获得奖励时调用该事件。请务必实现此事件，在用户观看广告后给予奖励。
    required void Function(AdWithoutView, RewardItem) onUserEarnedReward,
    Function()? onAdClosedCallback,
    Function()? onAdFailedCallback,
  }) async {
    ReportUtils.logEvent("ad_trigger", properties: {
      "position": title,
      "ad_type": "re_show 激励广告",
    });

    _onRewardedAdClosedCallback = onAdClosedCallback;
    _onRewardedAdFailedCallback = onAdFailedCallback;
    bool res = true;
    String errorMessage = '';
    // 检查广告是否正在显示
    if (_isRewardedAdShowing) {
      BusinessTools.log('激励广告已经在展示中');
      res = false;
      errorMessage = '激励广告已经在展示中';
    }
    // 检查广告是否已加载
    if (!_isRewardedAdLoaded || _rewardedAd == null) {
      BusinessTools.log('激励广告未准备好');
      loadRewardedAd();
      _onRewardedAdFailedCallback?.call();
      res = false;
      errorMessage = '激励广告未准备好';
    }
    if (!res) {
      ReportUtils.logEvent("ad_show_fail", properties: {
        "position": title,
        "ad_type": "rv_show 激励广告",
        "error": errorMessage,
        "pass_time": _rewardedAdRequestTime,
      });
      return res;
    }
    // 显示广告
    BusinessTools.log('正在显示激励广告');
    //上报
    ReportUtils.logEvent("rv_show", properties: {
      "position": title,
    });
    await _rewardedAd!.show(onUserEarnedReward: onUserEarnedReward);
    return true;
  }

  // 设置收益上报
  void profitReport(
      {required Ad ad,
      required double valueMicros,
      required PrecisionType precision,
      required String currencyCode,
      required String adFormat}) {
    if (!ConfigBusiness.config.releaseAdvertisement) {
      return;
    }
    // 计算收益（从微价值转换为实际价值）
    final double revenue = valueMicros / 1000000.0;
    final ResponseInfo? responseInfo = ad.responseInfo;

    // 上报广告收益
    ReportUtils.reportToAdjust(
      revenue: revenue, // 收益金额
      currencyCode: currencyCode, // 货币代码
      adNetwork: responseInfo?.loadedAdapterResponseInfo?.adSourceName ?? "", // 广告网络
      adUnit: ad.adUnitId, // 广告单元ID
      adPlacement: responseInfo?.loadedAdapterResponseInfo?.adSourceInstanceName ?? "", // 广告位置
    );
    ReportUtils.reportToFirebase(
      adPlatform: 'AdMob', // 广告平台
      adSource: responseInfo?.mediationAdapterClassName ?? 'AdMob', // 广告来源
      adUnitName: ad.adUnitId, // 广告单元名称
      adFormat: adFormat, // 广告格式
      value: revenue, // 收益金额
      currency: currencyCode, // 货币单位
    );

    // 记录日志
    BusinessTools.log('开屏广告收益: $revenue $currencyCode, 精度: $precision');
  }

  @override
  void onClose() {
    _cancelAppOpenRetryTimer();
    _cancelInterstitialRetryTimer();
    _cancelRewardedRetryTimer();
    _appOpenAd?.dispose();
    _interstitialAd?.dispose();
    _rewardedAd?.dispose();
    super.onClose();
  }
}
